package fasdk

import (
	"gitee.com/bupt-zkjc/fabric2.2-interface/config_yaml"
	"gitee.com/bupt-zkjc/fabric2.2-interface/constant"
	//config_ "gitee.com/bupt-zkjc/fabric2.2-interface/config"
	"gitee.com/bupt-zkjc/fabric2.2-interface/model"
	"fmt"
	"gitee.com/bupt-zkjc/fabric-sdk-go/pkg/client/msp"
	"gitee.com/bupt-zkjc/fabric-sdk-go/pkg/core/config"
	"gitee.com/bupt-zkjc/fabric-sdk-go/pkg/fabsdk"
	"path/filepath"
)
type FabricCAClient struct {
	ChainName      string
	Orgs           []string
	OrgAdmin       string
	User           model.FabricUser

	caClients      []*msp.Client
	sdk            *fabsdk.FabricSDK
}

func (fca *FabricCAClient) CASetup() error {
	path, err := config_yaml.GetCurrentPath()
	if err != nil{
		return err
	}
	configFile := filepath.Join(path, "config_" + fca.ChainName + constant.Yaml)
	fmt.Println(configFile)
	sdk, err := fabsdk.New(config.FromFile(configFile))
	if err != nil {
		logger.Error("failed to create SDK")
		return err
	}
	fca.sdk = sdk
	caClients := make([]*msp.Client, 0)
	for _, v := range fca.Orgs {
		caClient, err := msp.New(sdk.Context(fabsdk.WithUser(fca.OrgAdmin), fabsdk.WithOrg(v)))
		if err != nil {
			logger.Errorf("Failed to create channel management client: %s", err)
			return err
		}
		caClients = append(caClients, caClient)
	}
	fca.caClients = caClients

	return nil
}

func (fca *FabricCAClient) registerUser(user model.FabricUser) error {

	//ctxProvider := fca.sdk.Context()
	//
	//// Get the Client.
	//// Without WithOrg option, it uses default client organization.
	//msp1, err := msp.New(ctxProvider)
	//if err != nil {
	//	fmt.Printf("failed to create CA client: %s", err)
	//}
	for _, caclient := range fca.caClients {
		request := &msp.RegistrationRequest{
			Name:        user.UserName,
			Secret:      user.Secret,
			Type:        user.Type,
			Affiliation: user.Affiliation,
			Attributes:  user.Attributes,
		}
		_, err := caclient.Register(request)
		if err != nil {
			logger.Error(err)
			return err
		}
	}
	return nil
}

func (fca *FabricCAClient) enrollUser() error {

	_, err := fca.caClients[0].GetSigningIdentity(fca.User.UserName)
	if err == msp.ErrUserNotFound {
		logger.Info("Going to enroll user")
		err = fca.caClients[0].Enroll(fca.User.UserName, msp.WithSecret(fca.User.Secret))

		if err != nil {
			logger.Errorf("Failed to enroll user: %s\n", err)
			return err
		} else {
			logger.Infof("Success enroll user: %s\n", fca.User.UserName)
		}
	} else if err != nil {
		logger.Errorf("Failed to get user: %s\n", err)
		return err
	} else {
		logger.Infof("User %s already enrolled, skip enrollment.\n", fca.User.UserName)
	}
	return nil
}
func (fca *FabricCAClient) reenrollUser() error {

	_, err := fca.caClients[0].GetSigningIdentity(fca.User.UserName)
	if err == msp.ErrUserNotFound {
		logger.Info("Going to enroll user")
		err = fca.caClients[0].Reenroll(fca.User.UserName)

		if err != nil {
			logger.Errorf("Failed to reenroll user: %s\n", err)
			return err
		} else {
			logger.Infof("Success reenroll user: %s\n", fca.User.UserName)
		}
	} else if err != nil {
		logger.Errorf("Failed to get user: %s\n", err)
		return err
	} else {
		logger.Infof("User %s already enrolled, skip enrollment.\n", fca.User.UserName)
	}
	return nil
}
func (fca *FabricCAClient) revokeUser(reason string) error {
	request := &msp.RevocationRequest{
		Name:        fca.User.UserName,
		Reason:      reason,
		//CAName:      caName,
		GenCRL:      true,
	}
	_, err := fca.caClients[0].GetSigningIdentity(fca.User.UserName)
	if err == msp.ErrUserNotFound {
		logger.Info("Going to enroll user")
		_, err := fca.caClients[0].Revoke(request)

		if err != nil {
			logger.Errorf("Failed to enroll user: %s\n", err)
			return err
		} else {
			logger.Infof("Success revoke user: %s\n", fca.User.UserName)
		}
	} else if err != nil {
		logger.Errorf("Failed to get user: %s\n", err)
		return err
	} else {
		logger.Infof("User %s already enrolled, skip enrollment.\n", fca.User.UserName)
	}
	return nil
}